package org.celery.modules.ticket.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.celery.modules.shop.entity.Shop;
import org.celery.modules.shop.service.IShopService;
import org.celery.modules.ticket.entity.CustomTicket;
import org.celery.modules.ticket.excel.CustomTicketExcel;
import org.celery.modules.ticket.vo.CustomTicketVO;
import org.celery.modules.ticket.mapper.CustomTicketMapper;
import org.celery.modules.ticket.service.ICustomTicketService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单登记表 服务实现类
 *
 * @author Celery
 * @since 2023-09-23
 */
@Service
@AllArgsConstructor
public class CustomTicketServiceImpl extends BaseServiceImpl<CustomTicketMapper, CustomTicket> implements ICustomTicketService {

	private final IShopService shopService;

	@Override
	public IPage<CustomTicketVO> selectCustomTicketPage(IPage<CustomTicketVO> page, CustomTicketVO customTicket) {
		return page.setRecords(baseMapper.selectCustomTicketPage(page, customTicket));
	}

	@Override
	public List<Map<String, Object>> staticsList(String shopName, LocalDateTime startTime, LocalDateTime endTime, String tenantId, BladeUser user) {
		QueryWrapper<Shop> queryWrapper = new QueryWrapper<>();

		if (Func.isNotEmpty(shopName)) {
			queryWrapper.lambda().like(Shop::getResourceOwner, shopName);
		}

		if (Func.isNotEmpty(tenantId)) {
			queryWrapper.lambda().eq(Shop::getTenantId, tenantId);
		}

		if(!user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) || (!user.getRoleName().contains("administrator") && !user.getRoleName().contains("s_admin") && !user.getRoleName().contains("caiwu") && !user.getRoleName().contains("fake_boss"))) {
			List<Shop> shopList = shopService.authList(user);
			if (Func.isEmpty(shopList)) {
				return new ArrayList<>();
			}

			List<String> shopNameList = shopList.stream().map(Shop::getResourceOwner).collect(Collectors.toList());
			queryWrapper.lambda().in(Shop::getResourceOwner, shopNameList);
		}

		List<Shop> shopList = shopService.list(queryWrapper);
		List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());

		QueryWrapper<CustomTicket> queryWrapperTicket = new QueryWrapper<>();
		if (Func.isNotEmpty(startTime)) {
			queryWrapperTicket.lambda().between(CustomTicket::getDate, startTime, endTime);
		}
		List<CustomTicket> ticketList = list(queryWrapperTicket);

		List<Map<String, Object>> dataList = new ArrayList<>();
		Map<String, Object> allItem = new HashMap<>();
		// 总销售价格
		BigDecimal allTotalTicketAmount = new BigDecimal(0);
		// 总采购价格
		BigDecimal allTotalBuyAmount = new BigDecimal(0);
		// 总订单数
		Integer allTotalTicketCount = 0;
		// 有效订单数
		Integer allTotalActiveTicketCount = 0;
		// 退款订单
		Integer allTotalRefundTicketCount = 0;
		// 利润金额
		BigDecimal allTotalProfitAmount = new BigDecimal(0);
		for (CustomTicket ticket: ticketList) {
			if (!shopIdList.contains(ticket.getShopId())) {
				continue;
			}
			// 总计信息
			allTotalTicketCount++;
			if (ticket.getIsRefund().equals(0)) {
				allTotalActiveTicketCount++;
				allTotalTicketAmount = allTotalTicketAmount.add(ticket.getSalePrice());
				allTotalBuyAmount = allTotalBuyAmount.add(ticket.getPurchasePrice());
			} else {
				allTotalRefundTicketCount++;
			}
			allTotalProfitAmount = allTotalProfitAmount.add(ticket.getProfit());
		}

		allItem.put("shopId", "all");
		allItem.put("shopName", "全部");
		allItem.put("totalTicketAmount", allTotalTicketAmount);
		allItem.put("totalBuyAmount", allTotalBuyAmount);
		allItem.put("totalActiveTicketCount", allTotalActiveTicketCount);
		allItem.put("totalTicketCount", allTotalTicketCount);
		allItem.put("totalRefundTicketCount", allTotalRefundTicketCount);
		allItem.put("totalProfitAmount", allTotalProfitAmount);
		if (allTotalBuyAmount.equals(new BigDecimal(0))) {
			allItem.put("totalProfitRate", "0%");
		} else {
			allItem.put("totalProfitRate", allTotalProfitAmount.divide(allTotalBuyAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) + "%");
		}
		dataList.add(allItem);

		for (Shop shop: shopList) {
			Map<String, Object> data = new HashMap<>();
			// 总销售价格
			BigDecimal totalTicketAmount = new BigDecimal(0);
			// 总采购价格
			BigDecimal totalBuyAmount = new BigDecimal(0);
			// 总订单数
			Integer totalTicketCount = 0;
			// 有效订单数
			Integer totalActiveTicketCount = 0;
			// 退款订单
			Integer totalRefundTicketCount = 0;
			// 利润金额
			BigDecimal totalProfitAmount = new BigDecimal(0);

			for (CustomTicket ticket: ticketList) {
				if (ticket.getShopId().equals(shop.getId())) {
					if (ticket.getIsRefund().equals(0)) {
						totalActiveTicketCount++;
						totalTicketAmount = totalTicketAmount.add(ticket.getSalePrice());
						totalBuyAmount = totalBuyAmount.add(ticket.getPurchasePrice());
					} else {
						totalRefundTicketCount++;
					}
					totalProfitAmount = totalProfitAmount.add(ticket.getProfit());
					totalTicketCount++;
				}
			}

			data.put("shopId", shop.getId().toString());
			data.put("shopName", shop.getResourceOwner());
			data.put("totalTicketAmount", totalTicketAmount);
			data.put("totalBuyAmount", totalBuyAmount);
			data.put("totalActiveTicketCount", totalActiveTicketCount);
			data.put("totalTicketCount", totalTicketCount);
			data.put("totalRefundTicketCount", totalRefundTicketCount);
			data.put("totalProfitAmount", totalProfitAmount);
			if (totalBuyAmount.equals(new BigDecimal(0))) {
				data.put("totalProfitRate", "0%");
			} else {
				data.put("totalProfitRate", totalProfitAmount.divide(totalBuyAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) + "%");
			}
			dataList.add(data);
		}
		return dataList;
	}

	@Override
	public void importData(List<CustomTicketExcel> list) {
		if (Func.isEmpty(list)) {
			return;
		}

		Date startDate = null;
		Date endDate = null;
		List<String> shopNameList = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			CustomTicketExcel item = list.get(i);
			if (i == 0) {
				startDate = DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT);
				endDate = DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT);
			}
			if (startDate.after(DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT))) {
				startDate = DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT);
			}
			if (endDate.before(DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT))) {
				endDate = DateUtil.parse(item.getDate(), DateUtil.DATE_FORMAT);
			}

			if (!shopNameList.contains(item.getShopName())) {
				shopNameList.add(item.getShopName());
			}
		}
		if (Func.isEmpty(shopNameList)) {
			return;
		}

		List<Shop> shopList = shopService.list(Wrappers.<Shop>lambdaQuery().in(Shop::getResourceOwner, shopNameList));
		if (Func.isEmpty(shopList)) {
			return;
		}

		List<CustomTicket> customTicketList = list(Wrappers.<CustomTicket>lambdaQuery()
				.in(CustomTicket::getShopId, shopList.stream().map(Shop::getId).collect(Collectors.toList()))
				.between(CustomTicket::getDate, startDate, endDate)
		);

		for (CustomTicketExcel item: list) {
			Long shopId = null;
			for (Shop shop: shopList) {
				if (shop.getResourceOwner().equals(item.getShopName())) {
					shopId = shop.getId();
				}
			}

			// 未匹配到店铺
			if (Func.isEmpty(shopId)) {
				continue;
			}

			boolean match = false;
			for (CustomTicket customTicket: customTicketList) {
				if (customTicket.getShopId().equals(shopId)) {
					match = true;
					break;
				}
			}

			CustomTicket customTicket = BeanUtil.copyProperties(item, CustomTicket.class);
			customTicket.setShopId(shopId);
			if (!match) {
				save(customTicket);
			} else {
				update(customTicket, Wrappers.<CustomTicket>lambdaUpdate().eq(CustomTicket::getShopId, shopId).eq(CustomTicket::getTicketNumber, customTicket.getTicketNumber()));
			}
		}
	}

}
